use crate::tools::common;
use chrono::{DateTime, Local};
use log::{error, info, warn};
use rand::Rng;
use rusqlite::{params, Connection, Error, Result};
use serde::{Deserialize, Serialize};
use uuid::Uuid;

use super::common::TYPE_PASS_GEN_SETTING;

#[derive(serde::Serialize)]
pub struct PassClass {
    pub c_id: String,
    pub c_name: String,
}

#[derive(serde::Serialize, Clone)]
pub struct PassItem {
    pub pass_id: String,
    pub pass_account: String,
    pub pass_password: String,
    pub pass_notes: String,
}

pub fn get_class() -> Result<Vec<PassClass>> {
    //let conn = db::connect()?;
    let bind = common::DB_CONNECT.lock().unwrap();
    let conn = bind.as_ref().unwrap();

    let stmt = conn.prepare("select * from tools_pass_class");
    let mut binding = stmt?;
    let class_iter = match binding.query_map([], |row| {
        Ok(PassClass {
            c_id: row.get("c_id")?,
            c_name: row.get("c_name")?,
        })
    }) {
        Ok(iter) => iter,
        Err(_) => {
            return Ok(Vec::new());
        }
    };

    let mut all_class = Vec::new();
    for c in class_iter {
        all_class.push(c?);
    }
    Ok(all_class)
}
pub fn del_pass_item(pass_id: &str) -> Result<()> {
    //let conn = db::connect()?;
    let bind = common::DB_CONNECT.lock().unwrap();
    let conn = bind.as_ref().unwrap();

    let sql = "delete from tools_pass where pass_id=?1";
    conn.execute(sql, params![pass_id])?;
    info!("已成功删除:{}", pass_id);
    refresh_pass_cache(conn)?;
    Ok(())
}
pub fn del_pass_class(c_id: &str) -> Result<()> {
    //let conn = db::connect()?;
    let bind = common::DB_CONNECT.lock().unwrap();
    let conn = bind.as_ref().unwrap();

    conn.execute("delete from tools_pass_class where c_id=?1", params![c_id])?;
    conn.execute("delete from tools_pass where c_id=?1", params![c_id])?;
    refresh_pass_cache(conn)?;

    Ok(())
}
pub fn save_pass_item_form(
    pass_id: &str,
    pass_account: &str,
    pass_password: &str,
    pass_notes: &str,
) -> Result<()> {
    //let conn = db::connect()?;
    let bind = common::DB_CONNECT.lock().unwrap();
    let conn = bind.as_ref().unwrap();

    if pass_id.is_empty() {
        //新增
        let uuid = Uuid::new_v4();
        let local_time: DateTime<Local> = Local::now();
        let format_time = local_time.format("%Y-%m-%d %H:%M:%S").to_string();

        let sql = r#"insert into tools_pass (pass_id,pass_account,pass_password,pass_notes,create_date,update_date) 
        values (?1,?2,?3,?4,?5,?6)"#;
        match conn.execute(
            sql,
            params![
                uuid.to_string(),
                pass_account,
                common::encrypt_str(pass_password),
                pass_notes,
                &format_time,
                &format_time
            ],
        ) {
            Ok(_) => Ok(()),
            Err(e) => {
                println!("{:?}", e);
                return Err(e);
            }
        }
    } else {
        //修改
        let local_time: DateTime<Local> = Local::now();
        let format_time = local_time.format("%Y-%m-%d %H:%M:%S").to_string();

        let sql = "update tools_pass set pass_account=?1,pass_password=?2,pass_notes=?3,update_date=?4 where pass_id=?5";
        match conn.execute(
            sql,
            params![
                pass_account,
                pass_password,
                pass_notes,
                format_time,
                pass_id
            ],
        ) {
            Ok(_) => Ok(()),
            Err(e) => {
                println!("{:?}", e);
                return Err(e);
            }
        }
    }

    //Ok(())
}

pub fn get_pass_items(key_word: &str) -> Result<Vec<PassItem>> {
    if key_word.is_empty() {
        let pc = common::PASS_ITEMS_CACHE.clone();
        return Ok(pc.lock().unwrap().to_vec());
    } else {
        let pc = common::PASS_ITEMS_CACHE.clone();
        let mut ret: Vec<PassItem> = Vec::new();
        for i in pc.lock().unwrap().to_vec() {
            if i.pass_account.contains(key_word) || i.pass_notes.contains(key_word) {
                ret.push(i.clone());
            }
        }
        return Ok(ret);
    }
}
pub fn refresh_pass_cache(conn: &Connection) -> Result<()> {
    info!("进入刷新pass_cache方法。");
    //let conn = db::connect()?;

    let sql = "select * from tools_pass";
    let stmt = conn.prepare(sql);
    info!("进入刷新pass_cache方法。3");
    let mut binding = stmt?;
    info!("进入刷新pass_cache方法。4");
    let pass_iter = match binding.query_map([], |row| {
        //info!("进入刷新pass_cache方法。5");
        Ok(PassItem {
            pass_id: row.get("pass_id")?,
            pass_account: row.get("pass_account")?,
            pass_password: row.get("pass_password")?,
            pass_notes: row.get("pass_notes")?,
        })
    }) {
        Ok(iter) => iter,
        Err(_) => {
            info!("进入刷新pass_cache方法。6");
            return Ok(());
        }
    };

    info!("执行到这里...");
    common::PASS_ITEMS_CACHE.lock().unwrap().clear();

    for p in pass_iter {
        common::PASS_ITEMS_CACHE.lock().unwrap().push(p?);
    }

    Ok(())
}
pub fn save_class(c_id: &str, c_name: &str) -> Result<()> {
    //let conn = db::connect()?;
    let bind = common::DB_CONNECT.lock().unwrap();
    let conn = bind.as_ref().unwrap();

    if c_id.is_empty() {
        let uuid = Uuid::new_v4();
        let local_time: DateTime<Local> = Local::now();
        let format_time = local_time.format("%Y-%m-%d %H:%M:%S").to_string();

        let sql = r#"insert into tools_pass_class (c_id,c_name,create_date,update_date) 
        values (?1,?2,?3,?4)"#;
        match conn.execute(
            sql,
            params![uuid.to_string(), c_name, &format_time, &format_time],
        ) {
            Ok(_) => Ok(()),
            Err(e) => {
                println!("{:?}", e);
                return Err(e);
            }
        }
    } else {
        let local_time: DateTime<Local> = Local::now();
        let format_time = local_time.format("%Y-%m-%d %H:%M:%S").to_string();

        let sql = "update tools_pass_class set c_name=?1,update_date=?2 where c_id=?3";
        match conn.execute(sql, params![c_name, format_time, c_id]) {
            Ok(_) => Ok(()),
            Err(e) => {
                println!("{:?}", e);
                return Err(e);
            }
        }
    }
}
pub fn save_pass_gen_setting(setting: &str) -> Result<()> {
    //let conn = db::connect()?;
    let bind = common::DB_CONNECT.lock().unwrap();
    let conn = bind.as_ref().unwrap();

    let exist: bool = conn.query_row(
        "select exists (select 1 from tools_setting where s_type=?1 limit 1)",
        params![&TYPE_PASS_GEN_SETTING],
        |row| row.get(0),
    )?;

    if exist {
        let local_time: DateTime<Local> = Local::now();
        let format_time = local_time.format("%Y-%m-%d %H:%M:%S").to_string();

        let sql = "update tools_setting set s_value=?1,update_date=?2 where s_type=?3";
        match conn.execute(sql, params![setting, format_time, &TYPE_PASS_GEN_SETTING]) {
            Ok(_) => Ok(()),
            Err(e) => {
                println!("{:?}", e);
                return Err(e);
            }
        }
    } else {
        //新增
        let uuid = Uuid::new_v4();
        let local_time: DateTime<Local> = Local::now();
        let format_time = local_time.format("%Y-%m-%d %H:%M:%S").to_string();

        let sql = r#"insert into tools_setting (s_id,s_title,s_type,s_value,create_date,update_date) 
        values (?1,?2,?3,?4,?5,?6)"#;
        match conn.execute(
            sql,
            params![
                uuid.to_string(),
                "密码生成器配置",
                &TYPE_PASS_GEN_SETTING,
                setting,
                &format_time,
                &format_time
            ],
        ) {
            Ok(_) => Ok(()),
            Err(e) => {
                println!("{:?}", e);
                return Err(e);
            }
        }
    }
}
const U_LETTER: [&str; 26] = [
    "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S",
    "T", "U", "V", "W", "X", "Y", "Z",
];
const L_LETTER: [&str; 26] = [
    "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s",
    "t", "u", "v", "w", "x", "y", "z",
];
const N_NUMBER: [&str; 10] = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"];
const S_CHAR: [&str; 14] = [
    ",", ".", "}", "{", ";", ":", "?", "@", "#", "*", "-", "_", "=", "+",
];

pub fn gen_pass() -> String {
    #[derive(Serialize, Deserialize, Debug)]
    struct Setting {
        length: u16,
        uppercaseLetter: bool,
        lowercaseLetters: bool,
        number: bool,
        specialCharacters: bool,
        exclude: bool,
    }
    // if common::PASS_GEN_SETTING.lock().unwrap().is_empty(){
    //     //查询规则
    //     match common::get_setting_item(&common::TYPE_PASS_GEN_SETTING){
    //         Ok(items) =>{
    //             //查到了规则
    //             let v: Setting = serde_json::from_str(&items.s_value).unwrap();
    //             let mut rng = rand::thread_rng();

    //             let _i = 0;

    //             loop {
    //                 let index = rng.gen_range(0..26);
    //                 print!("{}",index);
    //                 if _i == v.length{
    //                     break;
    //                 }
    //             }
    //         },
    //         Err(e)=>{

    //         }
    //     }
    // }
    let exclude = vec!["0", "l", "1", "o", "O"];
    match common::get_setting_item(&common::TYPE_PASS_GEN_SETTING) {
        Ok(items) => {
            //查到了规则
            let v: Setting = serde_json::from_str(&items.s_value).unwrap();
            let mut rng = rand::thread_rng();

            let mut _i = 0;
            println!("{:?}", v);
            let mut dict = Vec::new();
            if v.uppercaseLetter {
                dict.extend_from_slice(&U_LETTER);
            }
            if v.lowercaseLetters {
                dict.extend_from_slice(&L_LETTER);
            }
            if v.number {
                dict.extend_from_slice(&N_NUMBER);
            }
            if v.specialCharacters {
                dict.extend_from_slice(&S_CHAR);
            }
            let mut ret = Vec::new();
            loop {
                let index = rng.gen_range(0..dict.len());
                let t_v: &str;
                match dict.get(index) {
                    Some(v) => t_v = *v,
                    None => t_v = "a",
                }

                if v.exclude {
                    if !exclude.contains(&t_v) {
                        ret.push(t_v);
                        _i += 1;
                    }
                } else {
                    _i += 1;
                }

                if _i == v.length {
                    break;
                }
            }
            println!("");
            println!("{}", ret.join(""));
            ret.join("")
        }
        Err(e) => {
            println!("{:?}", e);
            "error".to_string()
        }
    }
}
